package com.xiaomaoguai.crs.common.websocket;

import com.alibaba.fastjson.JSON;
import com.xiaomaoguai.crs.common.constants.Constants;
import com.xiaomaoguai.crs.common.constants.PushMessageType;
import com.xiaomaoguai.crs.common.model.WebSocketMessageModel;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * webSocket-消息处理类
 *
 * @ ClassName: TextMessageHandler.java
 * @ Author: WeiHui-Z
 * @ Date: 2016/12/22 10:56
 * @ Version: v1.0.0
 */
public class TextMessageHandler extends TextWebSocketHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(TextMessageHandler.class);

    //k-sessionId,v-WebSocketSession
    private static final Map<String, WebSocketSession> USER_SESSIONS = new ConcurrentHashMap<>();

    /**
     * 链接成功后会触发此方法，可在此处对离线消息什么的进行处理
     *
     * @param session session
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        put(session);
    }

    /**
     * 处理webSocket消息,前端 webSocket.send() 会触发此方法
     *
     * @param session session
     * @param message 消息
     * @throws Exception ex
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        LOGGER.debug("message -> " + message.getPayload());
    }

    /**
     * 前台调用ws.close() 会进入此方法
     *
     * @param session session
     * @param status  status
     * @throws Exception ex
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        remove(session);
    }

    /**
     * 将会话保存起来
     *
     * @param session session
     * @throws IOException 异常
     */
    private void put(WebSocketSession session) throws IOException {
        String sessionId = (String) session.getAttributes().get(HttpSessionHandshakeInterceptor.HTTP_SESSION_ID_ATTR_NAME);
        String userCode = (String) session.getAttributes().get(Constants.CURRENT_USER);
        if (StringUtils.isNoneBlank(sessionId, userCode)) {
            USER_SESSIONS.put(sessionId, session);
            session.sendMessage(new TextMessage(userCode + " webSocket链接成功!!"));
        }
    }

    /**
     * 移除用户信息
     *
     * @param session session
     */
    private void remove(WebSocketSession session) {
        String sessionId = (String) session.getAttributes().get(HttpSessionHandshakeInterceptor.HTTP_SESSION_ID_ATTR_NAME);
        String userCode = (String) session.getAttributes().get(Constants.CURRENT_USER);
        if (StringUtils.isNoneBlank(sessionId, userCode)) {
            //从map中移除session
            USER_SESSIONS.remove(sessionId);
        }
    }

    /**
     * 发送消息给指定用户
     *
     * @param userCode 用户
     * @param message  消息内容
     */
    private void sendMessageToUser(String userCode, String message) {
        Set<Map.Entry<String, WebSocketSession>> entries = USER_SESSIONS.entrySet();
        for (Map.Entry<String, WebSocketSession> sessionEntry : entries) {
            WebSocketSession socketSession = sessionEntry.getValue();
            if (userCode.equals(socketSession.getAttributes().get(Constants.CURRENT_USER)) && socketSession.isOpen()) {
                try {
                    socketSession.sendMessage(new TextMessage(message));
                    break;
                } catch (IOException e) {
                    LOGGER.error("webSocket推送消息给前台出错.", e);
                }
            }
        }
    }

    /**
     * 推送消息
     *
     * @param message 消息
     */
    public void pushMessage(WebSocketMessageModel message) {
        switch (message.getType()) {
            case PushMessageType.PUSH_NOTICE:
                //pushNotice(message);
                break;
            case PushMessageType.PUSH_WARING://超时预警
            case PushMessageType.PUSH_WARING_GROUP://超时预警
            case PushMessageType.PUSH_TASK: //获取任务
            case PushMessageType.PUSH_CANCEL_CONTRACT: //销售取消提醒
            case PushMessageType.PUSH_MANAGER_REJECT_CONTRACT: //销售经理否决提醒
                final List<String> messageReceivers = message.getReceivers();
                for (String userId : messageReceivers) {
                    sendMessageToUser(userId, JSON.toJSONString(message));
                }
                break;
            default:
                break;
        }
    }

}